﻿@using HardHatCore.ApiModels.Plugin_BaseClasses;
@using HardHatCore.ApiModels.Plugin_Interfaces;
@using HardHatCore.ApiModels.Responses;
@using HardHatCore.ApiModels.Shared.TaskResultTypes;
@using HardHatCore.HardHatC2Client.Models;
@using HardHatCore.HardHatC2Client.Pages;
@using System.Collections.Concurrent
@using HardHatCore.HardHatC2Client.Plugin_BaseClasses;
@using HardHatCore.HardHatC2Client.Plugin_Interfaces;
@using HardHatCore.HardHatC2Client.Services;
@using HardHatCore.HardHatC2Client.Utilities
@using System.Diagnostics;
@using HardHatCore.ApiModels.Shared;
@using static HardHatCore.HardHatC2Client.Pages.ImplantInteract;
@inject IJSRuntime JSRuntime

<MudExpansionPanel Style="background:#32333d; color:white;" @ref="@interactConPanel" IsExpandedChanged="(e)=>ExpandedChanged(e,implant,currenttask.Id,this)">
    <TitleContent>
        @if (PickedUpTasks.Contains(currenttask.Id) && !(TaskResultDic.ContainsKey(currenttask)))
        {
            <div class="d-flex">
                <MudProgressCircular Size="Size.Small" Color="Color.Primary" Indeterminate="true" Class="mr-3" />
                <MudIconButton Icon="@Icons.Material.Filled.Cancel" Size="Size.Small" Color="Color.Error" OnClick="() => CancelTask(currenttask.Id, implant.Metadata.Id)"></MudIconButton>
                <MudText>@commandHeaderText</MudText>
                <MudIconButton Class="mx-5" Icon="@Icons.Material.Filled.ContentCopy" Size="Size.Small" Color="Color.Primary" OnClick="() => CopyTaskCommand(commandHeaderText)"></MudIconButton>
            </div>
        }
        else if (CardContent != null)
        {
            if (CardContent.Status == ExtImplantTaskStatus.Running)
            {
                <div class="d-flex">
                    <MudProgressCircular Size="Size.Small" Color="Color.Success" Indeterminate="true" Class="mr-3" />
                    <MudIconButton class="mx-5" Icon="@Icons.Material.Filled.Cancel" Size="Size.Small" Color="Color.Error" OnClick="() => CancelTask(currenttask.Id, implant.Metadata.Id)"></MudIconButton>
                    <MudText>@commandHeaderText</MudText>
                    <MudIconButton Class="mx-5" Icon="@Icons.Material.Filled.ContentCopy" Size="Size.Small" Color="Color.Primary" OnClick="() => CopyTaskCommand(commandHeaderText)"></MudIconButton>
                </div>
            }
            else
            {
               // Console.WriteLine($"Card result is in panel should be setting status to {CardContent.Status.ToString()}");
                <div class="d-flex">
                @if (ImplantInteract.PanelExpandedOnce.ContainsKey(currenttask.Id))
                {
                    <MudIcon Icon=@setIcon(CardContent) Color=@SetColor(CardContent) class="mr-3"></MudIcon>
                }
                else
                {
                    <MudBadge Dot="true" Color="Color.Primary" Class="mr-3">
                        <MudIcon Icon=@setIcon(CardContent) Color=@SetColor(CardContent) class="mr-3"></MudIcon>
                    </MudBadge>
                }
                <MudText>@commandHeaderText</MudText>
                <MudIconButton Class="mx-5" Icon="@Icons.Material.Filled.ContentCopy" Size="Size.Small" Color="Color.Primary" OnClick="() => CopyTaskCommand(commandHeaderText)"></MudIconButton>
                <MudSpacer/>
                    @if(Tag.Existing_Tags.Count >0)
                    {
                        string taskChipName = GetKeyByValue(Tag.Task_Tags, currenttask.Id);
                        @if (!String.IsNullOrEmpty(taskChipName))
                        {
                            <MudChip Size="Size.Small" Style="@Objectives.setChipStyle(taskChipName)" Class="mr-3">@taskChipName</MudChip>
                        }
                        <MudIconButton class="mx-5" Icon="@Icons.Outlined.Label" Size="Size.Small" Color="Color.Primary" OnClick="() => SelectTaskTagChip(currenttask.Id)"></MudIconButton>
                    }
                </div>
            }
        }
        else
        {
            <div class="d-flex">
                <MudIcon Icon=@setIcon(CardContent) Color=@SetColor(CardContent) class="mr-3"></MudIcon>
                <MudText>@commandHeaderText</MudText>
                <MudIconButton Class="mx-5" Icon="@Icons.Material.Filled.ContentCopy" Size="Size.Small" Color="Color.Primary" OnClick="() => CopyTaskCommand(commandHeaderText)"></MudIconButton>
            </div>
        }
    </TitleContent>
    <ChildContent>
        <InteractWindowContentChildComponent @ref=childcard currenttask="@currenttask" implant="@implant" CardContent="@CardContent"></InteractWindowContentChildComponent>
    </ChildContent>
</MudExpansionPanel><!--This is the end of per input and output card -->

<style>
    .background-blur {
        backdrop-filter: blur(10px);
    }
</style>

@code {

    // private bool shouldRender = true;
    [Inject]
    private IDialogService DialogService { get; set; }
    [Parameter]
    public ExtImplantTaskResult_Base? CardContent { get; set; } = null;
    [Parameter]
    public string? commandHeaderText { get; set; } = null;
    [Parameter]
    public ExtImplantTask_Base currenttask { get; set; }
    [Parameter]
    public ExtImplant_Base implant { get; set; }
    [Parameter]
    public MudExpansionPanel? interactConPanel { get; set; }
    private InteractWindowContentChildComponent childcard;
    private bool isInitialized = false;
    private bool pendingUpdate = true;

    public async Task UpdateAsync()
    {
        //check if this panel has been initialized before if not then initialize it
        if (isInitialized)
        {
            if (CardContent != null && IsTaskResultInFinalState(CardContent))
            {
                //should be the final refresh before should render starts returning false 
                await InvokeAsync(StateHasChanged);
               // Console.WriteLine("should render is now false");
                pendingUpdate = false;
            }
            else
            {
                pendingUpdate = true;
                await InvokeAsync(StateHasChanged);
            }
        }
    }

    public async Task ExpandedChanged(bool IsExpanded, ExtImplant_Base implant, string taskId, InteractWindowContent interactWindow)
    {
        try
        {
            //Console.WriteLine("ExpandedChanged called");
            childcard.ShouldLoadCard = IsExpanded;

            //var task = OutGoingTasks[implant].FirstOrDefault(x => x.Id == taskId,defaultValue: null);
            if (!PanelExpandedOnce.ContainsKey(taskId))
            {
                PanelExpandedOnce.Add(taskId, true);
                string username = Login.SignedInUser;
                HardHatHubClient._hub.UpdateTaskResponseSeenNotif(username, taskId, implant.Metadata.Id);
            }
            else if (PanelExpandedOnce[taskId] == false)
            {
                PanelExpandedOnce[taskId] = true;
                string username = Login.SignedInUser;
                HardHatHubClient._hub.UpdateTaskResponseSeenNotif(username, taskId, implant.Metadata.Id);
            }

            //if isChanged is false then the panel has been closed, if it is true the panel is open
            if (childcard.ShouldLoadCard && childcard.FinishedLoading == false)
            {
                //Console.WriteLine("Panel opened & content not in finalized state refreshing");
                StateHasChanged();
            }
            if (!childcard.ShouldLoadCard)
            {
                //Console.WriteLine("Panel is closed refreshing");
                StateHasChanged();
            }
            else
            {
                string contentstate;
                if (childcard.FinishedLoading)
                {
                    contentstate = "finalized";
                }
                else
                {
                    contentstate = "not finalized";
                }
                //Console.WriteLine($"Panel is {childcard.ShouldLoadCard} and content is {contentstate}");
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
            Console.WriteLine(e.StackTrace);
        }

    }

    private async void TaskButtonTest()
    {
        bool? result = await DialogService.ShowMessageBox("Test","I was opened from a expansion panel header!", yesText: "yay!", cancelText: "Failure");
        StateHasChanged();
    }

    //set the icon and color for commands
    private string setIcon(IExtImplantTaskResult currenttask)
    {
        if(currenttask == null)
        {
            return Icons.Filled.Info;
        }
        if (currenttask.Status == ExtImplantTaskStatus.Complete)
        {
            return Icons.Filled.CheckCircle;
        }
        else if (currenttask.Status == ExtImplantTaskStatus.Cancelled)
        {
            return Icons.Filled.StopCircle;
        }
        else if (currenttask.Status == ExtImplantTaskStatus.Failed)
        {
            return Icons.Filled.SmsFailed;
        }
        else if (currenttask.Status == ExtImplantTaskStatus.FailedWithWarnings)
        {
            return Icons.Filled.Warning;
        }
        else if (currenttask.Status == ExtImplantTaskStatus.CompleteWithErrors)
        {
            return Icons.Filled.CheckCircle;
        }
        else
        {
            return Icons.Filled.Info;
        }

    }

    private Color SetColor(IExtImplantTaskResult currenttask)
    {
        if (currenttask == null)
        {
            return Color.Info;
        }
        if (currenttask.Status == ExtImplantTaskStatus.Complete)
        {
            return Color.Success;
        }
        else if (currenttask.Status == ExtImplantTaskStatus.Cancelled)
        {
            return Color.Secondary;
        }
        else if (currenttask.Status == ExtImplantTaskStatus.Failed)
        {
            return Color.Error;
        }
        else if (currenttask.Status == ExtImplantTaskStatus.FailedWithWarnings)
        {
            return Color.Warning;
        }
        else if (currenttask.Status == ExtImplantTaskStatus.CompleteWithErrors)
        {
            return Color.Warning;
        }
        else
        {
            return Color.Info;
        }
    }

    public async Task SelectTaskTagChip(string taskid)
    {
        //a message box to pick the tag name for the task
        var options = new DialogOptions { ClassBackground = "background-blur", MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
        var dialog = DialogService.Show<TagSelectionDialog>("Select Tag",options);
        var result = await dialog.Result;
        if (!result.Cancelled)
        {
            string tagName = result.Data.ToString();
            if (Tag.Task_Tags.ContainsKey(tagName))
            {
                Tag.Task_Tags[tagName].Add(taskid);
            }
            else
            {
                Tag.Task_Tags.Add(tagName, new List<string>() { taskid });
            }
        }
    }

    public static string GetKeyByValue(Dictionary<string, List<string>> dict, string targetValue)
    {
        foreach (KeyValuePair<string, List<string>> kvp in dict)
        {
            if (kvp.Value.Contains(targetValue))
            {
                return kvp.Key;
            }
        }
        return null; 
    }

    public async Task CopyTaskCommand(string CommandHeader)
    {
        //split the command header on the first instance of to everything to the right of that is the command string 
        string Command = CommandHeader.Split(new string[] { "to" }, 2, StringSplitOptions.None)[1];

        //copy the command to the clipboard
        await JSRuntime.InvokeVoidAsync("navigator.clipboard.writeText", Command.Trim());
        Implants.ShowInfoToast("Command Copied to Clipboard");
    }


    public async Task CancelTask(string taskid, string implantid)
    {
        DialogOptions options = new DialogOptions() { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Medium, FullWidth = true };

        var dialog = DialogService.Show<YesNoSimpleMudDialog>("Are you sure you want to cancel running task", options);
        //if the result is true then add the new profile to the list
        var result = await dialog.Result;

        if (!result.Cancelled)
        {
            await HardHatHubClient._hub.CancelRunningTask(taskid, implantid);
            Implants.ShowInfoToast($"Request to cancel task {taskid} sent");
        }
    }


    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender && pendingUpdate)
        {
            while(pendingUpdate)
            {
                //sleep the thread for 2 seconds, then run the update again
                await Task.Delay(2000);
                await UpdateAsync();
            }
        }
    }

    protected override bool ShouldRender()
    {
        if (!pendingUpdate)
        {
            return false;
        }
        return true;
    }
   
    protected override void OnInitialized()
    {
        isInitialized = true;
    }
}
